package m.framework.controller;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.Set;

import m.framework.dao.mapping.BeanField;
import m.framework.dao.mapping.BeanInfo;
import m.framework.dao.mapping.PrimitiveType;
import m.framework.dao.model.BaseModel;
import m.framework.dao.selector.Operators;
import m.framework.dao.selector.Query;
import m.framework.dao.selector.QueryField;
import m.framework.utils.BeanUtil;
import m.framework.utils.ClassUtil;
import m.framework.utils.StringUtil;

/** 将request绑定到java对象 */
public class MyBinder {

	public static Object bind(Map<String, String[]> request,Class paraClass) {
		return bind(request, paraClass,null);
	}
	
	public static Object bind(Map<String, String[]> request,Class paraClass, Type type) {
		if (ClassUtil.isInstance(paraClass, BaseModel.class)) {
			return bindModel(request, paraClass);
		}
		if (ClassUtil.isInstance(paraClass, Query.class)) {
			Type[] types = ((ParameterizedType) type).getActualTypeArguments();
			Class modelclass=(Class) types[0];
			Query query = Query.forClass(modelclass);
			return bindQuery(request, query);
		}
		if(ClassUtil.isInstance(paraClass, List.class)){
			Type[] types = ((ParameterizedType) type).getActualTypeArguments();
			Class modelclass=(Class) types[0];
			return bindList(request, modelclass);
		}
		return bindBean(request,paraClass);
	}
	
	//将request弄到list里面
	private static List bindList(Map<String, String[]> request, Class realClass) {
		TreeMap<Integer, Object> map=new TreeMap<Integer, Object>();
		Set<Entry<String,String[]>> en=request.entrySet();
		for(BeanField bf:BeanInfo.getBeanInfo(realClass).getDbFields()){
			for(Entry<String,String[]> e:en){
				String key=e.getKey();
				if(key.startsWith(bf.getName()+"[")){
					String idxStr=key.substring(bf.getName().length()+1, e.getKey().length()-1);
					int index=Integer.parseInt(idxStr);
					Object bean=map.get(index);
					if(bean==null){
						bean=ClassUtil.newInstance(realClass);
						map.put(index, bean);
					}
					bf.setString(bean, e.getValue()[0]);
				}
			}
		}
		return new ArrayList(map.values());
	}

	private static Object bindBean(Map<String, String[]> request, Class clazz) {
		Object bean=ClassUtil.newInstance(clazz);
		for(Method method:clazz.getMethods()){
			//以set开头
			if(!method.getName().startsWith("set")){
				continue;
			}
			//参数只有1个
			Class[] pras=method.getParameterTypes();
			if(pras.length>1){
				continue;
			}
			String fieldName=method.getName().substring("set".length());
			fieldName=StringUtil.firstLower(fieldName);
			String[] value=request.get(fieldName);
			if(value==null||value.length==0){
				continue;
			}
			BeanUtil.setSimpleValue(bean, fieldName,value[0],pras[0]);	
		}
		return bean;
	}

	/**
	 * 通过request对象创建查询器
	 * 
	 * @param request 实际是requestMap
	 * @param modelClass 要查询的类
	 * 
	 * */
	private static Query bindQuery(Map<String, String[]> request, Query query) {
		query.setOrder(getFirst(request, "orderField"), getFirst(request, "orderType"));
		
		if (getFirst(request, "rowsPerPage") != null) {
			int rowsPerPage = ClassUtil.toInt(getFirst(request, "rowsPerPage"));
			query.setRowsPerPage(rowsPerPage);
		}

		List condition = new ArrayList();
		BeanInfo bean = BeanInfo.getBeanInfo(query.modelClass());
		for (BeanField bf : bean.getDbFields()) {
			String[] s = request.get(bf.getName());
			if (s != null && s.length != 0 && StringUtil.isNotEmpty(s[0])) {
				if (s.length > 1) {
					condition.add(new QueryField(bf, Operators.IN, s));
				} else {
					s = s[0].trim().split(",");
					if (s.length > 1) {
						condition.add(new QueryField(bf, Operators.IN, s));
					} else {
						condition.add(new QueryField(bf, Operators.EQ, s[0]));
					}
				}
			}

			// 处理开始和结束
			condition=addBeginEnd(request, bf,condition);

			// 处理模糊查询
			condition=addfuzzy(request, bf,condition);
		}
		query.setCondition(condition);
		
		return query;
				
	}
	
	//新增模糊查查条件,页面参数如果以Fuzzy结尾查询时用模糊查询
	private static List addfuzzy(Map<String, String[]> request, BeanField bf, List condition) {
		if (bf.getPrimitiveType() == null || bf.getPrimitiveType()!=PrimitiveType.STRING) {
			return condition;
		}
		
		Object vs = getFirst(request, bf.getName() + "Fuzzy");
		if (vs != null&&!"".equals(vs)) {
			condition.add(new QueryField(bf, Operators.EQ, "%"+vs+"%"));
		}
		return condition;
	}

	private static List addBeginEnd(Map<String, String[]> request, BeanField bf,List condition) {
		if (bf.getPrimitiveType() == null || !bf.getPrimitiveType().compareAble()) {
			return condition;
		}
		// 处理begin
		Object vs = getFirst(request, bf.getName() + "Begin");
		if (vs != null) {
			condition.add(new QueryField(bf, Operators.GE, vs));
		}
		// 处理end
		vs = getFirst(request, bf.getName() + "End");
		if (vs != null) {
			condition.add(new QueryField(bf, Operators.LT, vs));
		}
		return condition;
	}
	

	private static String getFirst(Map<String, String[]> request, String name) {
		String[] s = request.get(name);
		if (s == null || s.length == 0) {
			return null;
		}
		if (StringUtil.isEmpty(s[0])) {
			return null;
		}
		return s[0];
	}

	private static Object bindModel(Map<String, String[]> request, Class clazz) {
		Set<Entry<String, String[]>> set = request.entrySet();
		BeanInfo bi = BeanInfo.getBeanInfo(clazz);
		BaseModel model = bi.newInstance();
		for (Entry<String, String[]> en : set) {
			for (BeanField bf : bi.getDbFields()) {
				if (bf.getName().equalsIgnoreCase(en.getKey())) {
					bf.setString(model, en.getValue()[0]);
				}
			}
		}
		return model;
	}

}
